package com.whl215.kit.adapter

import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.whl215.kit.adapter.element.GrapeElement
import com.whl215.kit.adapter.element.GrapeAction
import com.whl215.kit.adapter.element.ListStatusGrapeElement
import com.whl215.kit.adapter.element.LoadMoreGrapeElement

/**
 * author： happiness
 * date： 2021/2/25
 * description：RecyclerView Adapter base类
 */
abstract class GrapeBaseAdapter<T> : RecyclerView.Adapter<GrapeViewHolder>() {
    companion object {
        const val VIEW_TYPE_CONTENT = 0
        const val VIEW_TYPE_LIST_STATUS = 1
        const val VIEW_TYPE_LOAD_MORE = 2
    }

    private val mHandler = Handler(Looper.getMainLooper())
    protected var mList = mutableListOf<T>()
    var loadMoreElement: LoadMoreGrapeElement = LoadMoreGrapeElement()
    var listStatusElement: ListStatusGrapeElement = ListStatusGrapeElement()
    var loadMoreAction: GrapeAction? = GrapeAction.buildLoadMoreBeginAction()
        set(value) {
            field = value
            mHandler.post { notifyItemChanged(mList.size) }
        }
    var listStatusAction: GrapeAction? = null
        set(value) {
            listStatusElement.ableShowListStatus = true
            field = value
            notifyDataSetChanged()
        }

    var onChildClickListener: OnChildClickListener? = null
        set(value) {
            field = value
        }
    var onItemClickListener: OnItemClickListener? = null
        set(value) {
            field = value
        }
    var onItemLongClickListener: OnItemLongClickListener? = null
        set(value) {
            field = value
        }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GrapeViewHolder {
        if (viewType == VIEW_TYPE_LOAD_MORE) {
            return loadMoreElement.buildViewHolder(parent)
        } else if (viewType == VIEW_TYPE_LIST_STATUS) {
            return listStatusElement.buildViewHolder(parent)
        } else {
            val viewHolder = buildViewHolder(parent, viewType)
            setListener(viewHolder)
            return viewHolder
        }
    }

    abstract fun buildViewHolder(parent: ViewGroup, viewType: Int): GrapeViewHolder

    abstract fun convert(holder: GrapeViewHolder, position: Int, item: T)

    override fun onBindViewHolder(holder: GrapeViewHolder, position: Int) {
        val viewType = getItemViewType(position)
        if (viewType == VIEW_TYPE_LOAD_MORE) {
            loadMoreAction?.let {
                loadMoreElement.currCode = it.code
                loadMoreElement.bindViewHolder(holder, it)

            }
            when (loadMoreAction?.code) {
                GrapeAction.LOAD_MORE_BEGIN -> {
                    loadMoreElement.loadMore()
                }
                GrapeAction.LOAD_MORE_END -> {
                    loadMoreAction = GrapeAction.buildLoadMoreBeginAction()
                }
            }

        } else if (viewType == VIEW_TYPE_LIST_STATUS) {
            listStatusAction?.let {
                listStatusElement.currCode = it.code
                listStatusElement.bindViewHolder(holder, it)
            }
        } else {
            convert(holder, position, mList[position])
        }
    }

    override fun getItemCount(): Int {
        var count = mList.size
        if (mList.isEmpty()) {
            //数据为空 展示状态视图
            if (listStatusElement.ableShowListStatus) count = count.plus(1)
        } else {
            //有数据并且 允许加载更多 添加加载更多视图
            if (loadMoreElement.ableLoadMore) count = count.plus(1)
        }
        return count
    }

    override fun getItemViewType(position: Int): Int {
        var viewType = VIEW_TYPE_CONTENT
        if (mList.isEmpty() && listStatusElement.ableShowListStatus) {
            //无数据 展示状态视图
            viewType = VIEW_TYPE_LIST_STATUS
        } else {
            //有数据 并设置了加载更多 展示加载更多视图
            if (loadMoreElement.ableLoadMore && position == mList.size) {
                viewType = VIEW_TYPE_LOAD_MORE
            }
        }
        return viewType
    }

    open fun setData(list: List<T>) {
        listStatusElement.ableShowListStatus = false
        mList.clear()
        mList.addAll(list)
        notifyDataSetChanged()
    }

    open fun addData(index: Int = -1, list: List<T>) {
        if (list.isNotEmpty()) {
            var startIndex = 0
            val itemCount = list.size
            if (index >= 0) {
                startIndex = index
                mList.addAll(index, list)
            } else {
                startIndex = mList.size
                mList.addAll(list)
            }
            notifyItemRangeInserted(startIndex, itemCount)
        }
    }

    open fun addData(index: Int = -1, item: T) {
        var insertIndex = 0
        if (index >= 0) {
            insertIndex = index
            mList.add(index, item)
        } else {
            mList.add(item)
            insertIndex = mList.size
        }

        notifyItemInserted(insertIndex)
    }

    open fun removeAt(index: Int) {
        if (index >= mList.size) {
            throw IndexOutOfBoundsException()
        }
        mList.removeAt(index)
        notifyItemRemoved(index)
    }

    open fun remove(element: T) {
        mList.remove(element)
        notifyDataSetChanged()
    }

    fun removeAll(startPosition: Int = -1, list: Collection<T>) {
        mList.removeAll(list)
        if (startPosition == -1) {
            notifyDataSetChanged()
        } else {
            notifyItemRangeRemoved(startPosition, list.size)
        }
    }

    fun clear() {
        mList.clear()
        notifyDataSetChanged()
    }

    fun getItem(position: Int): T {
        return mList[position]
    }
    fun getList():List<T>{
        return mList
    }

    private fun setListener(holder: GrapeViewHolder) {
        if (onItemClickListener != null) {
            holder.itemView.setOnClickListener {
                onItemClickListener?.onItemClick(this, it, holder.adapterPosition)
            }
        }
        if (onItemLongClickListener != null) {
            holder.itemView.setOnLongClickListener {
                onItemLongClickListener?.onItemLongClick(this, it, holder.adapterPosition) ?: false
            }
        }
        if (onChildClickListener != null) {
            holder.setOnClickListener(View.OnClickListener { view ->
                onChildClickListener?.onChildClick(this, view, holder.adapterPosition)
            })
        }
    }

    interface OnItemClickListener {
        fun onItemClick(adapter: GrapeBaseAdapter<*>, view: View, position: Int)
    }

    interface OnItemLongClickListener {
        fun onItemLongClick(
            adapter: GrapeBaseAdapter<*>, view: View, position: Int
        ): Boolean
    }

    interface OnChildClickListener {
        fun onChildClick(adapter: GrapeBaseAdapter<*>, view: View, position: Int)
    }


}